home *** CD-ROM | disk | FTP | other *** search
/ By Popular Request 2.0 / By Popular Request 2.0 (Arsenal Computer).ISO / amiga_6 / unrar100.lzx / unrar.c < prev    next >
C/C++ Source or Header  |  2002-07-28  |  20KB  |  824 lines

  1. /******    *****   ******
  2.  **   **  **   **  **   **      unRAR utility version 1.00e
  3.  ******   *******  ******       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4.  **   **  **   **  **   **         FREE portable version
  5.  **   **  **   **  **   **         ~~~~~~~~~~~~~~~~~~~~~
  6.  
  7.          Main code
  8.  
  9.    YOU CAN CHANGE FOLLOWING CODE IN ORDER TO ACHIEVE
  10.    COMPATIBILITY WITH YOUR OPERATING MEDIA.
  11.  
  12.    PLEASE SEND ALL NOTES, PATCHES TO ANY RAR SITE (SEE RAR_SITE.TXT IN RAR)
  13.    OR DIRECTLY TO THE AUTHOR CONTACT SITE: andrey@vybor.chel.su
  14.                                   FIDOnet: Andrey Spasibozhko, 2:5010/23
  15.    VOICE REPORTS: +7-3512-130-231
  16.  
  17.  
  18.    NOTE: This code was modified by Derek Clarke to compile correctly on
  19.          SAS/C V6.x for the Amiga operating system.
  20.  
  21. */
  22.  
  23. #include "unrar.h"          /* definitions */
  24. #include "unpack.c"         /* unpacking procedures */
  25.  
  26. void main(int, char **);
  27. void   SplitCommandLine(int, char **);  /* parses command string */
  28. int    CmpName(char *, char *);           /* checks name for mask */
  29. char*  PointToName(char *);       /* returns pathname */
  30. void   NextVolumeName(void);    /* gets next volume name */
  31. void   SplitName(char *, char *, char *);         /* splits pathname */
  32. void   ExecuteCommand(void);    /* executes extr. command */
  33. void   ListArchive(void);       /* lists archive contents */
  34. int    ExtrFile(void);          /* extracts single file */
  35. void   Help(void);              /* prints usage help */
  36. void   ShutDown(int);          /* stops working */
  37. void   ErrExit(int, int);           /* exits with error code */
  38. void   CreatePath(char *);        /* creates path */
  39. int    tread(FILE *, void *, unsigned);             /* reads with checking */
  40. void   tclose(FILE *);            /* closes with checking */
  41. void   MergeArc(int);          /* to next volume */
  42. void   UnstoreFile(void);       /* unpacks non-compressed file */
  43. int    IsArchive(void);         /* checks for RAR archive signature */
  44. void   CheckArc(void);          /* similar but with exit */
  45. int    strnicomp(char *, char *, int);         /* compares strings */
  46. char*  strtolwr(char *);          /* convert string to lowercase */
  47. int    ToPercent(long, long);         /* calculates percentage */
  48. int    ReadBlock(int);         /* reads archive block */
  49. int    IsProcessFile(int);     /* should file be processed */
  50. int    UnpRead(UBYTE *, UWORD);           /* reading while unpacking */
  51. int    UnpWrite(UBYTE *, UWORD);          /* writing while unpacking */
  52. void   InitCRC(void);           /* initializes CRC table */
  53. UDWORD CRC(UDWORD, UBYTE *, UWORD);               /* calculates CRC */
  54.  
  55. struct MarkHeader MarkHead;
  56. struct ArchiveHeader Mhd;
  57. struct FileHeader Lhd;
  58.  
  59. UDWORD CRC32_Table[256],UnpFileCRC;
  60. HPBYTE TmpMemory;
  61.  
  62. int ArgCount=0;
  63. char ArgNames[16][80],MainCommand;
  64. char CurExtrFile[80]={0},ArcName[80],ArcFileName[80],ExtrPath[80];
  65. int SolidType,UnpVolume,TestMode,ExitCode=0;
  66. FILE *ArcFPtr=NULL,*FileFPtr=NULL,*RdUnpFPtr,*WrUnpFPtr;
  67. long NextBlockPos,UnpPackedSize;
  68.  
  69. char VerStr[]= "$VER: UNRAR 1.1 (19.3.95) Amiga Port by Derek Clarke";
  70.  
  71. void main(int Argc, char *Argv[])
  72. {
  73.   printf("\nAmiga UnRAR V1.1 by Derek Clarke\n");
  74.   printf("Based on UNRAR V1.00e ⌐ 1994 Eugene Roshal\n");
  75.   if ((TmpMemory=(HPBYTE)MEMALLOC(UNP_MEMORY))==NULL)
  76.     ErrExit(EMEMORY,MEMORY_ERROR);
  77.   MakeTbl();
  78.   SplitCommandLine(Argc,Argv);
  79.   ExecuteCommand();
  80.   ShutDown(SD_MEMORY);
  81.   exit(ExitCode);
  82. }
  83.  
  84.  
  85. int CmpName(char *Mask, char *Name)
  86. {
  87.   while (1)
  88.   {
  89.     if (*Mask=='*')
  90.     {
  91.       while (*Mask!='.' && *Mask!=0)
  92.         Mask++;
  93.       while (*Name!='.' && *Name!=0)
  94.         Name++;
  95.     }
  96.     if (*Mask==0)
  97.       return(*Name==0);
  98.     if (*Name==0 && *Mask=='.')
  99.     {
  100.       Mask++;
  101.       continue;
  102.     }
  103.     if (toupper(*Mask)==toupper(*Name) || *Mask=='?' && *Name!=0)
  104.     {
  105.       Mask++;
  106.       Name++;
  107.     }
  108.     else
  109.       return(0);
  110.   }
  111. }
  112.  
  113.  
  114. void ErrExit(int ErrCode, int Code)
  115. {
  116.   char ErrMsg[80];
  117.   switch(ErrCode)
  118.   {
  119.     case EEMPTY:
  120.       strcpy(ErrMsg,"");
  121.       break;
  122.     case EWRITE:
  123.       strcpy(ErrMsg,"Write error.  Disk full?");
  124.       break;
  125.     case EREAD:
  126.       strcpy(ErrMsg,"Read error.");
  127.       break;
  128.     case EOPEN:
  129.       strcpy(ErrMsg,"File open error.");
  130.       break;
  131.     case ECLOSE:
  132.       strcpy(ErrMsg,"File close error.");
  133.       break;
  134.     case EMEMORY:
  135.       strcpy(ErrMsg,"Not enough memory.");
  136.       break;
  137.     case EARCH:
  138.       strcpy(ErrMsg,"Broken archive.");
  139.       break;
  140.   }
  141.   if (ErrCode!=EEMPTY)
  142.     printf("\n Program aborted.\n %s",ErrMsg);
  143.   ShutDown(SD_FILES | SD_MEMORY);
  144.   exit(Code);
  145. }
  146.  
  147.  
  148. void CreatePath(char *fpath)
  149. {
  150.   char *ChPtr;
  151.   ChPtr=fpath;
  152.   while(*ChPtr!=0 && (ChPtr=strchr(ChPtr,PATHDIV))!=NULL)
  153.   {
  154.     *ChPtr=0;
  155.     if (MAKEDIR(fpath)==0)
  156.       printf("\n Creating    %-55s",fpath);
  157.     *ChPtr=PATHDIV;
  158.     ChPtr++;
  159.   }
  160. }
  161.  
  162.  
  163. void NextVolumeName(void)
  164. {
  165.   char *ChPtr;
  166.   ChPtr=strrchr(ArcName,'.');
  167.   if (!isdigit(*(ChPtr+2)) || !isdigit(*(ChPtr+3)))
  168.     strcpy(ChPtr+2,"00");
  169.   else
  170.   {
  171.     ChPtr+=3;
  172.     while ((++(*ChPtr))=='9'+1)
  173.     {
  174.       if (*(ChPtr-1)=='.')
  175.       {
  176.         *ChPtr='A';
  177.         break;
  178.       }
  179.       else
  180.       {
  181.         *ChPtr='0';
  182.         ChPtr--;
  183.       }
  184.     }
  185.   }
  186. }
  187.  
  188.  
  189. void MergeArc(int ShowFileName)
  190. {
  191.   int Ch;
  192.   tclose(ArcFPtr);
  193.   NextVolumeName();
  194.   while ((ArcFPtr=fopen(ArcName,"r"))==NULL)
  195.   {
  196.     printf("\n Disk with %s required. Continue? ",ArcName);
  197.     Ch=getchar();
  198.     if (toupper(Ch)=='N')
  199.       ErrExit(EEMPTY,USER_BREAK);
  200.   }
  201.   if (MainCommand=='T')
  202.     printf("\n\n Testing archive %s",ArcName);
  203.   else
  204.     if (MainCommand!='P')
  205.       printf("\n\n Extracting from %s",ArcName);
  206.   CheckArc();
  207.   ReadBlock(FILE_HEAD);
  208.   if (ShowFileName)
  209.     printf("\n     ...     %-55s",ArcFileName);
  210.   UnpVolume=(Lhd.Flags & LHD_SPLIT_AFTER);
  211.   fseek(ArcFPtr,NextBlockPos-Lhd.PackSize,SEEK_SET);
  212.   UnpPackedSize=Lhd.PackSize;
  213.   RdUnpFPtr=ArcFPtr;
  214. }
  215.  
  216.  
  217. void UnstoreFile(void)
  218. {
  219.   int Code;
  220.   while ( 1 )
  221.   {
  222.     if ((Code=UnpRead((UBYTE *)TmpMemory,0x7f00))==-1)
  223.       ErrExit(EWRITE,WRITE_ERROR);
  224.     if (Code==0)
  225.       break;
  226.     if (UnpWrite((UBYTE *)TmpMemory,(UWORD)Code)==-1)
  227.       ErrExit(EWRITE,WRITE_ERROR);
  228.   }
  229. }
  230.  
  231.  
  232. int IsArchive(void)
  233. {
  234.   UBYTE Mark[7],Header[13];
  235.   SolidType=0;
  236.   if (tread(ArcFPtr,Mark,7)!=7)
  237.     return(0);
  238.   if (Mark[0]!=0x52 || Mark[1]!=0x61 || Mark[2]!=0x72 || Mark[3]!=0x21 ||
  239.       Mark[4]!=0x1a || Mark[5]!=0x07 || Mark[6]!=0x00)
  240.     return(0);
  241.   if (tread(ArcFPtr,Header,13) != 13)
  242.     return(0);
  243.   Mhd.HeadCRC  = Header[0]+(UWORD)Header[1]*0x100;
  244.   Mhd.HeadType = Header[2];
  245.   Mhd.Flags    = Header[3]+(UWORD)Header[4]*0x100;
  246.   Mhd.HeadSize = Header[5]+(UWORD)Header[6]*0x100;
  247.   if (!(Mhd.HeadCRC==(UWORD)~CRC(0xFFFFFFFFL,&Header[2],11)))
  248.     printf("\n Archive header broken");
  249.   SolidType=(Mhd.Flags & MHD_SOLID);
  250.   fseek(ArcFPtr,Mhd.HeadSize-13,SEEK_CUR);
  251.   return(1);
  252. }
  253.  
  254.  
  255. void CheckArc(void)
  256. {
  257.   if (!IsArchive())
  258.   {
  259.     printf("\nBad archive %s",ArcName);
  260.     ErrExit(EEMPTY,FATAL_ERROR);
  261.   }
  262. }
  263.  
  264.  
  265. int tread(FILE *FPtr, void *buf, unsigned len)
  266. {
  267.   int Code;
  268.   Code=fread(buf,1,len,FPtr);
  269.   if (Code==-1)
  270.     ErrExit(EREAD,FATAL_ERROR);
  271.   return(Code);
  272. }
  273.  
  274.  
  275. void tclose(FILE *FPtr)
  276. {
  277.   if (fclose(FPtr)==EOF)
  278.     ErrExit(ECLOSE,FATAL_ERROR);
  279. }
  280.  
  281.  
  282. char* PointToName(char *Path)
  283. {
  284.   char *ChPtr;
  285.   if ((ChPtr=strrchr(Path,PATHDIV))!=NULL)
  286.     return(ChPtr+1);
  287.   else
  288.     if ((ChPtr=strrchr(Path,':'))!=NULL)
  289.       return(ChPtr+1);
  290.     else
  291.       return(Path);
  292. }
  293.  
  294.  
  295. int strnicomp(char *Str1, char *Str2, int MaxLen)
  296. {
  297.   if (MaxLen==0)
  298.     return(0);
  299.   while (MaxLen-- > 0)
  300.   {
  301.     if (toupper(*Str1)!=toupper(*Str2))
  302.       return(1);
  303.     if (*Str1==0)
  304.       return(0);
  305.     Str1++;
  306.     Str2++;
  307.   }
  308.   return(0);
  309. }
  310.  
  311.  
  312. char* strtolwr(char *Str)
  313. {
  314.   char *ChPtr;
  315.   for (ChPtr=Str;*ChPtr!=0;ChPtr++)
  316.     *ChPtr=tolower(*ChPtr);
  317.   return(Str);
  318. }
  319.  
  320.  
  321. void SplitName(char *Path, char *Dir, char *Name)
  322. {
  323.   char *ChPtr,*ChPtr1;
  324.   if ((ChPtr=strrchr(Path,':'))!=NULL)
  325.     ChPtr++;
  326.   else
  327.     ChPtr=Path;
  328.   if ((ChPtr1=strrchr(ChPtr,PATHDIV))!=NULL)
  329.   {
  330.     *ChPtr1=0;
  331.     strcpy(Dir,ChPtr);
  332.     *ChPtr1=PATHDIV;
  333.     ChPtr=ChPtr1+1;
  334.   }
  335.   else
  336.     *Dir=0;
  337.   strcpy(Name,ChPtr);
  338. }
  339.  
  340.  
  341. int ToPercent(long N1, long N2)
  342. {
  343.   if (N1 > 10000)
  344.   {
  345.     N1/=100;
  346.     N2/=100;
  347.   }
  348.   if (N2==0)
  349.     return(0);
  350.   if (N2<N1)
  351.     return(100);
  352.   return((int)(N1*100/N2));
  353. }
  354.  
  355.  
  356. void SplitCommandLine(int Argc, char *Argv[])
  357. {
  358.   int I,Len;
  359.  
  360.   ArgCount = MainCommand = *ArcName = *ExtrPath = 0;
  361.  
  362.   if (Argc==2)
  363.   {
  364.     MainCommand='X';
  365.     strcpy(ArcName,Argv[1]);
  366.   }
  367.   else
  368.     for (I=1;I<Argc;I++)
  369.     {
  370.       if (MainCommand==0)
  371.         MainCommand=toupper(Argv[I][0]);
  372.       else
  373.       {
  374.         if (*ArcName==0)
  375.           strncpy(ArcName,Argv[I],80);
  376.         else
  377.         {
  378.           Len=strlen(Argv[I]);
  379.           if (Len>0 && (Argv[I][Len-1]==':' || (Argv[I][Len-1]=='\\' || Argv[I][Len-1]=='/')))
  380.           {
  381.             strcpy(ExtrPath,Argv[I]);
  382.             ExtrPath[Len-1]=PATHDIV;
  383.           }
  384.           else
  385.             strncpy(ArgNames[(ArgCount++) & 0x0f],Argv[I],80);
  386.         }
  387.       }
  388.     }
  389.  
  390.   if (ArgCount==0 && *ArcName!=0)
  391.     strcpy(ArgNames[(ArgCount++) & 0x0f],"*.*");
  392.   if (strrchr(PointToName(ArcName),'.')==NULL)
  393.     strcat(ArcName,isupper(*ArcName) ? ".RAR":".rar");
  394.   ArgCount &= 0xF;
  395. }
  396.  
  397.  
  398. void ExecuteCommand(void)
  399. {
  400.   switch(MainCommand)
  401.   {
  402.     case 'E':
  403.     case 'X':
  404.     case 'T':
  405.       ExtrFile();
  406.       break;
  407.     case 'V':
  408.     case 'L':
  409.       ListArchive();
  410.       break;
  411.     case 0:
  412.       Help();
  413.       exit(0);
  414.     default:
  415.       Help();
  416.       exit(USER_ERROR);
  417.   }
  418. }
  419.  
  420. void ShutDown(int Mode)
  421. {
  422.   if (Mode & SD_FILES)
  423.   {
  424.     if (ArcFPtr!=NULL)
  425.       fclose(ArcFPtr);
  426.     if (FileFPtr!=NULL)
  427.       fclose(FileFPtr);
  428.   }
  429.   if (Mode & SD_MEMORY)
  430.   {
  431.     if (TmpMemory!=NULL)
  432.       MEMFREE(TmpMemory);
  433.     printf("\n");
  434.   }
  435. }
  436.  
  437.  
  438. void Help(void)
  439. {
  440.   printf("\n Usage:     UNRAR <command> <archive> <files...>\n");
  441.   printf("\n <Commands>\n");
  442.   printf("\n x       Extract files with full path");
  443.   printf("\n e       Extract files to current directory");
  444.   printf("\n t       Test archive files");
  445.   printf("\n v       Verbosely list contents of archive");
  446.   printf("\n l       List contents of archive\n\n");
  447. }
  448.  
  449.  
  450. int ExtrFile(void)
  451. {
  452.   char DestFileName[80];
  453.   long FileCount=0,TotalFileCount=0,DirCount=0,ErrCount=0;
  454.   int ExtrFile=0,Size,SkipSolid=0,UnpSolid;
  455.  
  456.   if ((ArcFPtr=fopen(ArcName,"r"))==NULL)
  457.     ErrExit(EOPEN,FATAL_ERROR);
  458.  
  459.   CheckArc();
  460.   CreateEncTbl(TmpMemory);
  461.   UnpVolume=UnpSolid=0;
  462.   if (MainCommand=='T')
  463.     printf("\n Testing archive %s\n",ArcName);
  464.   else
  465.     printf("\n Extracting from %s\n",ArcName);
  466.  
  467.   while (1)
  468.   {
  469.     Size=ReadBlock(FILE_HEAD);
  470.  
  471.     if (Size<=0 && UnpVolume==0)
  472.       break;
  473.     if ((Lhd.Flags & LHD_SPLIT_BEFORE) && SolidType)
  474.     {
  475.       printf("\nSolid archive: first volume required");
  476.       ErrExit(EEMPTY,FATAL_ERROR);
  477.     }
  478.     if (UnpVolume && Size==0)
  479.       MergeArc(0);
  480.     UnpVolume=(Lhd.Flags & LHD_SPLIT_AFTER);
  481.     fseek(ArcFPtr,NextBlockPos-Lhd.PackSize,SEEK_SET);
  482.  
  483.     TestMode=0;
  484.     ExtrFile=0;
  485.     SkipSolid=0;
  486.  
  487.     if (IsProcessFile(COMPARE_PATH) && (Lhd.Flags & LHD_SPLIT_BEFORE)==0
  488.         || (SkipSolid=SolidType)!=0)
  489.     {
  490.  
  491.       strcpy(DestFileName,ExtrPath);
  492.       strcat(DestFileName,(MainCommand!='E') ? ArcFileName : PointToName(ArcFileName));
  493.  
  494.       ExtrFile=!SkipSolid;
  495.  
  496.       if (Lhd.UnpVer<15 || Lhd.UnpVer>UNP_VER)
  497.       {
  498.         printf("\n %s: unknown method",ArcFileName);
  499.         ExtrFile=0;
  500.         ErrCount++;
  501.         ExitCode=WARNING;
  502.       }
  503.  
  504.       if (Lhd.Flags & LHD_PASSWORD)
  505.       {
  506.         printf("\n %s: cannot process encrypted file",ArcFileName);
  507.         if (SolidType)
  508.           ErrExit(EEMPTY,FATAL_ERROR);
  509.         ExtrFile=0;
  510.         ErrCount++;
  511.         ExitCode=WARNING;
  512.       }
  513.  
  514.       if (Lhd.HostOS==MS_DOS && (Lhd.FileAttr & DOSFA_DIREC))
  515.       {
  516.         if (MainCommand=='E')
  517.           continue;
  518.         if (SkipSolid)
  519.         {
  520.           printf("\n Skipping    %-55s Ok",ArcFileName);
  521.           continue;
  522.         }
  523.         if (MainCommand=='T')
  524.         {
  525.           printf("\n Testing     %-55s Ok",ArcFileName);
  526.           continue;
  527.         }
  528.         CreatePath(DestFileName);
  529.         if (MAKEDIR(DestFileName)==0)
  530.           printf("\n Creating    %-55s",ArcFileName);
  531.         continue;
  532.       }
  533.       else
  534.       {
  535.         if (MainCommand=='T' && ExtrFile)
  536.           TestMode=1;
  537.         if ((MainCommand=='E' || MainCommand=='X') && ExtrFile)
  538.         {
  539.           CreatePath(DestFileName);
  540.           if ((FileFPtr=fopen(DestFileName,"w"))==NULL)
  541.           {
  542.             printf("\n Cannot create %s",DestFileName);
  543.             ExitCode=WARNING;
  544.             ExtrFile=0;
  545.           }
  546.         }
  547.       }
  548.  
  549.       if (!ExtrFile && SolidType)
  550.         SkipSolid=TestMode=ExtrFile=1;
  551.       if (ExtrFile)
  552.       {
  553.         TotalFileCount++;
  554.         if (SkipSolid)
  555.           printf("\n Skipping    %-55s",ArcFileName);
  556.         else
  557.         {
  558.           FileCount++;
  559.           switch(MainCommand)
  560.           {
  561.             case 'T':
  562.               printf("\n Testing     %-55s",ArcFileName);
  563.               break;
  564.             case 'X':
  565.             case 'E':
  566.               printf("\n Extracting  %-55s",DestFileName);
  567.               break;
  568.           }
  569.         }
  570.         strcpy(CurExtrFile,DestFileName);
  571.         UnpFileCRC=0xFFFFFFFFL;
  572.         UnpPackedSize=Lhd.PackSize;
  573.         DestUnpSize=Lhd.UnpSize;
  574.         RdUnpFPtr=ArcFPtr;
  575.         WrUnpFPtr=FileFPtr;
  576.         if (Lhd.Method==0x30)
  577.           UnstoreFile();
  578.         else
  579.           if (unpack(TmpMemory,UnpRead,UnpWrite,UnpSolid)==-1)
  580.             ErrExit(EWRITE,WRITE_ERROR);
  581.         if (TotalFileCount>0 && SolidType)
  582.           UnpSolid=1;
  583.         if (UnpFileCRC==~Lhd.FileCRC)
  584.         {
  585.           if (MainCommand!='P')
  586.             printf(" Ok");
  587.         }
  588.         else
  589.         {
  590.           fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  591.           printf("\n %-15s : CRC failed",ArcFileName);
  592.           ExitCode=CRC_ERROR;
  593.           ErrCount++;
  594.         }
  595.         if (!TestMode)
  596.         {
  597.           SETFILETIME(FileFPtr,(void *)&Lhd.FileTime);
  598.           tclose(FileFPtr);
  599.         }
  600.         TestMode=0;
  601.         *CurExtrFile=0;
  602.       }
  603.     }
  604.     if (!ExtrFile && !SolidType)
  605.       fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  606.   }
  607.   tclose(ArcFPtr);
  608.   if ((FileCount+DirCount)==0)
  609.   {
  610.     printf("\n No files");
  611.     ExitCode=WARNING;
  612.   }
  613.   else
  614.     if (ErrCount==0)
  615.       printf("\n  All OK");
  616.     else
  617.       printf("\n  Total errors: %ld",ErrCount);
  618.   return(0);
  619. }
  620.  
  621.  
  622. void ListArchive(void)
  623. {
  624.   unsigned long TotalPackSize,TotalUnpSize,FileCount;
  625.   int I;
  626.   TotalPackSize=TotalUnpSize=FileCount=0;
  627.   if ((ArcFPtr=fopen(ArcName,"r"))==NULL)
  628.     ErrExit(EOPEN,FATAL_ERROR);
  629.   CheckArc();
  630.   printf("\n ");
  631.   if (SolidType)
  632.     printf("Solid ");
  633.   if (Mhd.Flags & MHD_MULT_VOL)
  634.     printf("%colume ",(SolidType) ? 'v':'V');
  635.   else
  636.     printf("%crchive ",(SolidType) ? 'a':'A');
  637.   printf("%s\n",ArcName);
  638.   if (MainCommand=='V')
  639.     printf("\n Pathname/Comment\n%12.12s","");
  640.   else
  641.     printf("\n Name       ");
  642.   printf("      Size   Packed  Ratio   Date   Time  Attr   CRC-32  Meth Ver\n");
  643.   for (I=0;I<77;I++)
  644.     printf("-");
  645.   while(ReadBlock(FILE_HEAD) > 0)
  646.   {
  647.     if (IsProcessFile(NOT_COMPARE_PATH))
  648.     {
  649.       printf("\n%c",(Lhd.Flags & LHD_PASSWORD) ? '*' : ' ');
  650.       if (MainCommand=='V')
  651.       {
  652.         printf("%-s",ArcFileName);
  653.         printf("\n%12s ","");
  654.       }
  655.       else
  656.         printf("%-12s",PointToName(ArcFileName));
  657.  
  658.       printf(" %8ld %8ld ",Lhd.UnpSize,Lhd.PackSize);
  659.       if (Lhd.Flags & (LHD_SPLIT_AFTER | LHD_SPLIT_BEFORE))
  660.         printf(" Split");
  661.       else
  662.         printf(" %3d%% ",ToPercent(Lhd.PackSize,Lhd.UnpSize));
  663.  
  664.       printf(" %02d-%02d-%02d %02d:%02d ",Lhd.FileTime.ft_day,
  665.              Lhd.FileTime.ft_month,(Lhd.FileTime.ft_year+1980)%100,
  666.              Lhd.FileTime.ft_hour,Lhd.FileTime.ft_min);
  667.  
  668.       if (Lhd.HostOS==MS_DOS)
  669.         printf("%c%c%c%c%c",
  670.           (Lhd.FileAttr & DOSFA_DIREC ) ? 'D' : '.',
  671.           (Lhd.FileAttr & DOSFA_RDONLY) ? 'R' : '.',
  672.           (Lhd.FileAttr & DOSFA_HIDDEN) ? 'H' : '.',
  673.           (Lhd.FileAttr & DOSFA_SYSTEM) ? 'S' : '.',
  674.           (Lhd.FileAttr & DOSFA_ARCH  ) ? 'A' : '.');
  675.       else
  676.         printf("     ");
  677.       printf(" %8.8lX  m%d  %d.%d",Lhd.FileCRC,Lhd.Method-0x30,Lhd.UnpVer/10,Lhd.UnpVer%10);
  678.       if (!(Lhd.Flags & LHD_SPLIT_BEFORE))
  679.       {
  680.         TotalUnpSize+=Lhd.UnpSize;
  681.         FileCount++;
  682.       }
  683.       TotalPackSize+=Lhd.PackSize;
  684.     }
  685.     fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  686.   }
  687.   printf("\n");
  688.   for (I=0;I<77;I++)
  689.     printf("-");
  690.   printf("\n%5ld %16ld %8ld %4d%%\n",FileCount,TotalUnpSize,TotalPackSize,ToPercent(TotalPackSize,TotalUnpSize));
  691.   tclose(ArcFPtr);
  692. }
  693.  
  694.  
  695. int IsProcessFile(int ComparePath)
  696. {
  697.   int NumName,WildCards;
  698.   char ArgName[80],dir1[80],name1[15],dir2[80],name2[15];
  699.   for (NumName=0;NumName<ArgCount;NumName++)
  700.   {
  701.     memcpy((void *)ArgName,(void *)ArgNames[NumName],sizeof(ArgName));
  702.     WildCards=(strchr(ArgName,'?')!=NULL || strchr(ArgName,'*')!=NULL);
  703.     SplitName(ArgName,dir1,name1);
  704.     SplitName(ArcFileName,dir2,name2);
  705.     if (CmpName(name1,name2) && ((ComparePath==NOT_COMPARE_PATH && *dir1==0) ||
  706.           WildCards && strnicomp(dir1,dir2,strlen(dir1))==0 ||
  707.           strnicomp(dir1,dir2,1000)==0))
  708.       return(1);
  709.   }
  710.   return(0);
  711. }
  712.  
  713. int ReadBlock(int BlockType)
  714. {
  715.   UDWORD HeadCRC;
  716.   UBYTE Header[32];
  717.   int Size,I;
  718.   memset(&Lhd,0,sizeof(Lhd));
  719.   memset(Header,0,sizeof(Header));
  720.   while (1)
  721.   {
  722.     Size=tread(ArcFPtr,Header,32);
  723.     Lhd.HeadCRC  = Header[0] +(UWORD)Header[1]*0x100;
  724.     Lhd.HeadType = Header[2];
  725.     Lhd.Flags    = Header[3] +(UWORD)Header[4]*0x100;
  726.     Lhd.HeadSize = Header[5] +(UWORD)Header[6]*0x100;;
  727.     Lhd.PackSize = Header[7] +(UWORD)Header[8]*0x100+(UDWORD)Header[9]*0x10000L+(UDWORD)Header[10]*0x1000000L;
  728.     Lhd.UnpSize  = Header[11]+(UWORD)Header[12]*0x100+(UDWORD)Header[13]*0x10000L+(UDWORD)Header[14]*0x1000000L;
  729.     Lhd.HostOS   = Header[15];
  730.     Lhd.FileCRC  = Header[16]+(UWORD)Header[17]*0x100+(UDWORD)Header[18]*0x10000L+(UDWORD)Header[19]*0x1000000L;
  731.     *(UDWORD *)&Lhd.FileTime=Header[20]+(UWORD)Header[21]*0x100+(UDWORD)Header[22]*0x10000L+(UDWORD)Header[23]*0x1000000L;
  732.     Lhd.UnpVer   = Header[24];
  733.     Lhd.Method   = Header[25];
  734.     Lhd.NameSize = Header[26]+(UWORD)Header[27]*0x100;
  735.     Lhd.FileAttr = Header[28]+(UWORD)Header[29]*0x100+(UDWORD)Header[30]*0x10000L+(UDWORD)Header[31]*0x1000000L;
  736.     if (Size != 0 && (Size<7 || Lhd.HeadSize<7))
  737.       ErrExit(EARCH,FATAL_ERROR);
  738.     NextBlockPos=ftell(ArcFPtr)-Size+Lhd.HeadSize;
  739.     if (Lhd.Flags & LONG_BLOCK)
  740.       NextBlockPos+=Lhd.PackSize;
  741.     if (Size==0 || BlockType==ALL_HEAD || Lhd.HeadType==BlockType)
  742.       break;
  743.     fseek(ArcFPtr,NextBlockPos,SEEK_SET);
  744.   }
  745.   if (Size>0 && BlockType==FILE_HEAD)
  746.   {
  747.     tread(ArcFPtr,ArcFileName,Lhd.NameSize);
  748.     ArcFileName[Lhd.NameSize]=0;
  749.     Size+=Lhd.NameSize;
  750.     HeadCRC=CRC(0xFFFFFFFFL,&Header[2],30);
  751.     if (!(Lhd.HeadCRC==(UWORD)~CRC(HeadCRC,&ArcFileName[0],Lhd.NameSize)))
  752.       printf("\n %s: file header broken\n",ArcFileName);
  753.     for (I=0;ArcFileName[I];I++)
  754.       if (ArcFileName[I]=='\\' || ArcFileName[I]=='/')
  755.         ArcFileName[I]=PATHDIV;
  756.     if (Lhd.HostOS==MS_DOS)
  757.       strtolwr(ArcFileName);
  758.   }
  759.   return(Size);
  760. }
  761.  
  762.  
  763. int UnpRead(UBYTE *Addr, UWORD Count)
  764. {
  765.   int RetCode;
  766.   unsigned int ReadSize,TotalRead=0;
  767.   UBYTE *ReadAddr;
  768.   ReadAddr=Addr;
  769.   while (Count > 0)
  770.   {
  771.     ReadSize=(unsigned int)((Count>UnpPackedSize) ? UnpPackedSize : Count);
  772.     if ((RetCode=fread(ReadAddr,1,ReadSize,RdUnpFPtr))!=ReadSize)
  773.       break;
  774.     TotalRead+=RetCode;
  775.     ReadAddr+=RetCode;
  776.     Count-=RetCode;
  777.     UnpPackedSize-=RetCode;
  778.     if (UnpPackedSize == 0 && UnpVolume)
  779.       MergeArc(1);
  780.     else
  781.       break;
  782.   }
  783.   if (RetCode!=-1)
  784.     RetCode=(int)TotalRead;
  785.   return(RetCode);
  786. }
  787.  
  788.  
  789. int UnpWrite(UBYTE *Addr, UWORD Count)
  790. {
  791.   int RetCode;
  792.   if (TestMode)
  793.     RetCode=(int)Count;
  794.   else
  795.     if ((RetCode=fwrite(Addr,1,Count,WrUnpFPtr))!=Count)
  796.       RetCode = -1;
  797.   if (RetCode!=-1)
  798.     UnpFileCRC=CRC(UnpFileCRC,Addr,(UWORD)RetCode);
  799.   return(RetCode);
  800. }
  801.  
  802.  
  803. UDWORD CRC(UDWORD StartCRC, UBYTE *Addr, UWORD Size)
  804. {
  805.   UWORD I;
  806.   if (!CRC32_Table[1])
  807.     InitCRC();
  808.   for (I=0;I<Size;I++)
  809.     StartCRC = CRC32_Table[(UBYTE)StartCRC ^ Addr[I]] ^ (StartCRC >> 8);
  810.   return(StartCRC);
  811. }
  812.  
  813. void InitCRC(void)
  814. {
  815.   int I, J;
  816.   UDWORD C;
  817.   for (I=0;I<256;I++)
  818.   {
  819.     for (C=I,J=0;J<8;J++)
  820.       C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
  821.     CRC32_Table[I]=C;
  822.   }
  823. }
  824.